<template>
  <div class="upload-file-base">
    <div class="upload-box">
      <div class="upload-button-view">
        <slot name="btn">
          <el-button size="small" class="upload-btn" :disabled="disabled" @click="showFilePick">
            <i class="iconfont icon-upload"></i>
            {{ uploadTitle || '上传附件' }}
          </el-button>
        </slot>
        <slot name="others"></slot>
      </div>
      <slot name="tips">
        <div class="upload-tips" :class="{ inline: acceptInline }">{{ fileTypeTips }}</div>
      </slot>
      <input
        type="file"
        ref="fileInput"
        class="file-input"
        :accept="accept"
        :multiple="maxLimit > 1"
        @change="onFileChange" />
    </div>
    <div v-if="showProgress && uploading" class="progress-view">
      <el-progress :percentage="uploadProgress"></el-progress>
    </div>
    <img-cropper
      :visible.sync="cropperVisible"
      :img-url="imgCropUrl"
      :crop-width="imgCropperConfig.width"
      :crop-height="imgCropperConfig.height"
      @img-cropped="onImgCropped"
      @closed="resetCroppingData"></img-cropper>
  </div>
</template>

<script>
import { getFileTypeByName } from '@utility/utility'
import ImgCropper from './ImgCropper.vue'
export default {
  name: 'UploadFileBase',
  components: { ImgCropper },
  props: {
    fileList: {
      type: Array,
      default: () => [],
    },
    // 标题
    uploadTitle: {
      type: String,
      default: '上传附件',
    },
    // 数量限制
    maxLimit: {
      type: Number,
      default: 9,
    },
    accept: {
      type: String,
      default: '.pdf,.ofd,.doc,.docx,.xls,.xlsx,.wps,.jpeg,.png,.jpg',
    },
    // TODO 图片上传模式暂时只支持单张上传
    imgCropperConfig: {
      type: Object,
      default: () => ({
        enableCropper: false,
        width: 600,
        height: 400,
      }),
    },

    /**
     * function params uploadForm, onSuccess, onError, onProgress
     */
    httpRequest: {
      type: Function,
    },
    disabled: {
      type: Boolean,
    },
    layout: {
      type: String,
      default: 'list',
    },
    showProgress: {
      type: Boolean,
      default: true,
    },
    acceptInline: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      uploadProgress: 0,
      uploading: false,
      tempFileList: [], // 待上传的文件列表
      // imgCropList: [], // 图片裁剪列表
      imgCropUrl: null, // 图片裁剪地址
      imgCropItem: null, // 图片裁剪
      cropperVisible: false,
    }
  },
  computed: {
    fileTypeTips() {
      let text = ''
      if (this.accept) {
        text = `请上传${this.accept
          .replace(/\./g, '')
          .replace(/,/g, '、')}格式文件！最多上传9个附件,单次上传附件大小总和限制在20M以内`
      }
      return text
    },
  },
  watch: {},
  created() {},
  mounted() {},
  methods: {
    showFilePick() {
      if (!this.disabled) {
        this.$refs.fileInput.click()
      }
    },
    onFileChange(e) {
      const files = e.target.files
      console.log('files...', files.length)
      let invalid = false // 判断文件类型
      let insize = 0 // 判断文件大小

      // 判断是否有正在上传的文件
      if (this.uploading) {
        this.$message({
          message: '请等待其他文件上传完成！',
          type: 'warning',
        })
        this.resetFileSelect()
        return false
      }

      // 判断是否符合文件类型限制
      for (const item of files) {
        if (!this.accept.includes(getFileTypeByName(item.name))) {
          invalid = true
          break
        }
        console.log('item :>> ', item)
        insize += item.size / 1024 / 1024
        // if (item.size / 1024 / 1024 >= 20) {
        //   insize = true
        //   break
        // }
      }
      if (invalid) {
        this.$message.error('请选择指定的文件类型！')
        this.resetFileSelect()
        return
      }
      if (insize >= 20) {
        this.$message.error('单次上传附件大小总和限制在20M以内')
        this.resetFileSelect()
        return
      }

      // 判断是否超出限制
      if (this.fileList.length + files.length > this.maxLimit) {
        this.$message.warning(`最多只能上传${this.maxLimit}个文件！`)
        this.resetFileSelect()
        return
      }
      const selectedFiles = [...files]
      const imgFiles = selectedFiles.filter(item => {
        return item.type.includes('image')
      })
      // 如果需要图片裁剪，判断是否包含有图片
      if (this.imgCropperConfig.enableCropper && imgFiles.length) {
        if (imgFiles.length > 1) {
          this.$message.warning('图片裁剪模式只支持挑选一张图片，请重新选择！')
          this.resetFileSelect()
        } else {
          // this.imgCropList = imgFiles;
          this.imgCropItem = imgFiles[0]
          this.tempFileList = selectedFiles.filter(item => {
            return !item.type.includes('image')
          })
          this.imgCropUrl = URL.createObjectURL(this.imgCropItem)
          this.cropperVisible = true
        }
        return
      }

      this.tempFileList = [...files]
      this.$refs.fileInput.value = null
      // 调用上传接口
      this.callUploadRequest(this.tempFileList)
    },
    onImgCropped(imgBlob) {
      const imgFile = new File([imgBlob], this.imgCropItem.name)
      this.tempFileList.push(imgFile)
      this.callUploadRequest(this.tempFileList)
      this.resetCroppingData()
    },
    resetCroppingData() {
      this.imgCropUrl = null
      this.imgCropItem = null
      this.tempFileList = []
      this.resetFileSelect()
    },
    resetFileSelect() {
      this.$refs.fileInput.value = null
    },
    callUploadRequest(files) {
      const uploadRequest = this.httpRequest
      if (uploadRequest && typeof uploadRequest === 'function') {
        const uploadForm = new FormData()
        files.forEach(item => {
          uploadForm.append('files', item)
        })
        this.uploadProgress = 0
        this.uploading = true
        uploadRequest(uploadForm, this.onUploadSuccess, this.onUploadFailed, this.onUploadProgress)
      } else {
        this.$emit('upload', files)
      }
    },
    /* eslint-disable */
    onUploadSuccess(res) {
      this.uploading = false
      this.tempFileList = []
      const resFiles = res.data
      if (resFiles && resFiles.length) {
        this.fileList.push(
          ...resFiles.filter(item => {
            return item.name && item.fileType
          })
        )
      }
      this.$emit('change')
    },
    onUploadFailed() {
      this.uploading = false
      this.tempFileList = []
    },
    onFileRemove() {
      this.$emit('change')
    },
    onUploadProgress(progress) {
      console.log('onUploadProgress...', progress)
      if (progress === 100) {
        progress = 99
      }
      this.uploadProgress = progress
    },
  },
}
</script>

<style lang="scss" scoped>
.upload-file-base {
  .upload-box {
    .upload-button-view {
      display: inline-block;
      display: flex;
      align-items: center;
      .upload-btn {
        border-radius: 0;
        border-color: #3167b2;
        color: #3167b2;
        font-size: 16px;
        i {
          margin-right: 5px;
        }
        &.is-disabled {
          border-color: #ebeef5;
          color: #c0c4cc;
        }
      }
    }
    .file-input {
      display: none;
    }
    .upload-tips {
      margin-top: 10px;
      &.inline {
        display: inline-block;
        margin-left: 20px;
        margin-top: 0px;
      }
    }
  }
  .progress-view {
    margin-top: 20px;
  }
}
</style>
